﻿using System;
using System.Collections.Generic;
using System.Linq;

using RexToy.DesignPattern;
using RexToy.Xml;
using RexToy.Configuration;

namespace MGAS.Model
{
    using MGAS.Model.Entity;

    public class AllocMap : Singleton<AllocMap>
    {
        private static readonly char[] DELIMITER = { ',', ';' };

        private List<Building> _buildings;
        private List<Location> _locs;
        private List<SensorMeta> _s_metas;
        private List<byte> _ids;
        protected AllocMap()
        {
            _buildings = new List<Building>();
            _locs = new List<Location>();
            _s_metas = new List<SensorMeta>();
            _ids = new List<byte>();

            XDoc doc = XDoc.LoadFromFile(Configuration.GetAllocMap());

            var xBuildList = doc.NavigateToList("buildings/building");
            foreach (var x in xBuildList)
            {
                byte id = x.GetValue<byte>("@Id").Value;
                string text = x.GetStringValue("@Text");
                var building = new Building() { Id = id, Text = text };
                _buildings.Add(building);
            }

            var xLocList = doc.NavigateToList("locations/location");
            foreach (var x in xLocList)
            {
                byte id = x.GetValue<byte>("@Id").Value;
                byte buildingId = x.GetValue<byte>("@BuildingId").Value;
                byte floor = x.GetValue<byte>("@Floor").Value;
                string text = x.GetStringValue("@Text");

                var loc = new Location() { Id = id, BuildingId = buildingId, Floor = floor, Text = text };
                _locs.Add(loc);
            }

            var xMetaList = doc.NavigateToList("sensors/sensor");
            foreach (var x in xMetaList)
            {
                byte id = x.GetValue<byte>("@Id").Value;
                byte locationId = x.GetValue<byte>("@LocationId").Value;
                byte line = x.GetValue<byte>("@Line").Value;
                string text = x.GetStringValue("@Text");
                var meta = new SensorMeta() { Id = id, LocationId = locationId, Line = line, Text = text };
                _s_metas.Add(meta);
            }

            var xIds = doc.NavigateToSingle("id");
            string val = xIds.GetStringValue("@list");
            string[] ids = val.Split(DELIMITER, StringSplitOptions.RemoveEmptyEntries);
            foreach (var strId in ids)
            {
                _ids.Add(byte.Parse(strId.Trim()));
            }
        }

        public IEnumerable<Building> FindAllBuildings()
        {
            return _buildings.OrderByDescending(b => b.Id);
        }

        public IEnumerable<Location> FindAllLocations()
        {
            return _locs;
        }

        public Building FindBuildingByLocation(Location loc)
        {
            if (loc == null)
                return null;

            var q = from b in _buildings
                    where b.Id == loc.BuildingId
                    select b;
            return q.Single();
        }

        public SensorMeta FindSensorMeta(byte id)
        {
            var q = from s in _s_metas
                    where s.Id == id
                    select s;
            return q.Single();
        }

        public IEnumerable<SensorMeta> FindSensorByLocation(Location loc)
        {
            var q = from m in _s_metas
                    where m.LocationId == loc.Id
                    select m;
            return q;
        }

        public Location FindLocationBySensor(byte sensorId)
        {
            var sid = from s in _s_metas
                      where s.Id == sensorId
                      select s;

            if (sid.SingleOrDefault() == null)
                return null;

            var q = from l in _locs
                    where l.Id == sid.Single().LocationId
                    select l;

            return q.SingleOrDefault();
        }

        public IEnumerable<byte> GetSensorIds()
        {
            return _ids;
        }
    }
}
